package cn.cxyxj.study.webflux03.authentication.email;

import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import reactor.core.publisher.Mono;


/**
 * @author cxyxj
 */
@Component
public class EmailReactiveAuthenticationManager implements ReactiveAuthenticationManager {

    private EmailReactiveUserDetailsService emailReactiveUserDetailsService;

    public EmailReactiveAuthenticationManager(EmailReactiveUserDetailsService emailReactiveUserDetailsService) {
        Assert.notNull(emailReactiveUserDetailsService, "emailReactiveUserDetailsService cannot be null");
        this.emailReactiveUserDetailsService = emailReactiveUserDetailsService;
    }

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        Mono<UserDetails> userDetails = emailReactiveUserDetailsService.findByEmail(authentication.getPrincipal().toString());
        return userDetails
                // switchIfEmpty：当 userDetails 为空的时，抛出异常
                // 这里应该自定义一个异常类型，比如 EmailException，BadCredentialsException 是内置的异常类型。
                .switchIfEmpty(Mono.defer(() -> Mono.error(new RuntimeException("该邮箱不存在"))))
                .map(this::createUsernamePasswordAuthenticationToken);
    }
    private EmailVerificationCodeAuthenticationToken createUsernamePasswordAuthenticationToken(UserDetails userDetails) {
        return new EmailVerificationCodeAuthenticationToken(userDetails,
                userDetails.getAuthorities());
    }

}
